import os
import logging
import traceback
from datetime import datetime
import sys
from logging.handlers import RotatingFileHandler

# 全局日志记录器
logger = None

# 日志级别映射
LOG_LEVEL_MAP = {
    'DEBUG': logging.DEBUG,
    'INFO': logging.INFO,
    'WARNING': logging.WARNING,
    'ERROR': logging.ERROR,
    'CRITICAL': logging.CRITICAL
}

# 从配置获取日志设置
def get_logging_config():
    """从配置文件获取日志设置"""
    try:
        from config_utils import ConfigManager
        return ConfigManager.get_logging_config()
    except Exception as e:
            # 出错时使用默认配置
            # 使用基础异常处理而非打印
            return {
            'log_dir': 'logs',
            'log_level': 'INFO',
            'max_log_size': 10 * 1024 * 1024,
            'backup_count': 5,
            'enable_console': True
        }

# 确保日志目录存在
def _ensure_log_dir(log_dir):
    """确保日志目录存在
    
    Args:
        log_dir (str): 日志目录路径
    """
    if not os.path.exists(log_dir):
        try:
            os.makedirs(log_dir, exist_ok=True)
        except Exception as e:
            # 创建目录失败时静默处理，使用默认行为
            pass

# 自定义格式化器，支持消息截断
class TruncatedFormatter(logging.Formatter):
    """支持日志消息截断的格式化器"""
    
    def __init__(self, fmt=None, datefmt=None, max_message_length=5000):
        """
        初始化格式化器
        
        Args:
            fmt: 日志格式
            datefmt: 日期格式
            max_message_length: 最大消息长度，超过将被截断
        """
        super().__init__(fmt, datefmt)
        self.max_message_length = max_message_length
    
    def formatMessage(self, record):
        """格式化日志消息，超过长度限制时截断"""
        # 调用父类方法获取格式化后的消息
        formatted_message = super().formatMessage(record)
        
        # 检查消息长度
        if len(formatted_message) > self.max_message_length:
            # 计算截断位置，保留消息开头和结尾的重要信息
            truncate_at = self.max_message_length - 100  # 预留100个字符显示截断提示
            truncated_message = formatted_message[:truncate_at]
            # 添加截断提示
            truncated_message += f"... [日志消息过长，已截断，原始长度: {len(formatted_message)} 字符]"
            return truncated_message
        
        return formatted_message

# 获取格式化器
def _get_formatter():
    """获取日志格式化器"""
    return TruncatedFormatter(
        '%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S',
        max_message_length=5000  # 限制单条日志消息最大长度为5000字符
    )

# 初始化日志记录器
def init_logger():
    """初始化全局日志记录器"""
    global logger
    
    if logger is not None:
        return logger
    
    try:
        # 从配置获取日志设置
        logging_config = get_logging_config()
        log_dir = logging_config.get('log_dir', 'logs')
        log_level_str = logging_config.get('log_level', 'INFO')
        max_log_size = logging_config.get('max_log_size', 10 * 1024 * 1024)
        backup_count = logging_config.get('backup_count', 5)
        enable_console = logging_config.get('enable_console', True)
        
        # 转换日志级别
        log_level = LOG_LEVEL_MAP.get(log_level_str.upper(), logging.INFO)
        
        # 确保日志目录存在
        _ensure_log_dir(log_dir)
        
        # 创建日志文件路径
        log_file = os.path.join(log_dir, f'app_{datetime.now().strftime("%Y%m")}.log')
        
        # 创建日志记录器
        logger = logging.getLogger('RentalContractSystem')
        logger.setLevel(log_level)
        
        # 避免重复添加处理器
        if not logger.handlers:
            # 创建文件处理器（带轮转）
            file_handler = RotatingFileHandler(
                log_file,
                maxBytes=max_log_size,
                backupCount=backup_count,
                encoding='utf-8'
            )
            file_handler.setFormatter(_get_formatter())
            logger.addHandler(file_handler)
            
            # 创建控制台处理器（如果启用）
            if enable_console:
                # 使用优化的控制台处理器，避免输出缓冲区溢出
                console_handler = OptimizedStreamHandler(sys.stdout)
                console_handler.setFormatter(_get_formatter())
                logger.addHandler(console_handler)
            
            # 日志系统初始化完成 - 静默处理，避免递归依赖
    except Exception as e:
        # 初始化日志系统失败 - 静默处理，使用后备方案
        # 创建一个最小化的控制台日志记录器作为后备
        fallback_logger = logging.getLogger('FallbackLogger')
        fallback_logger.setLevel(logging.INFO)
        fallback_console = logging.StreamHandler(sys.stdout)
        fallback_logger.addHandler(fallback_console)
        logger = fallback_logger
    
    return logger

# 重新加载日志配置
def reload_logger_config():
    """重新加载日志配置"""
    global logger
    
    # 移除所有处理器
    if logger:
        for handler in logger.handlers[:]:
            handler.close()
            logger.removeHandler(handler)
        logger = None
    
    # 重新初始化
    return init_logger()

# 优化控制台输出的日志处理器
class OptimizedStreamHandler(logging.StreamHandler):
    """优化的控制台日志处理器，避免输出缓冲区溢出"""
    
    def emit(self, record):
        """重写emit方法，确保日志消息不会导致控制台缓冲区溢出"""
        try:
            # 限制发送到控制台的消息长度
            if len(record.getMessage()) > 1000:
                # 对于控制台输出，进一步限制长度
                record.msg = record.getMessage()[:1000] + "... [日志过长，完整内容请查看日志文件]"
                record.args = ()  # 清除参数，避免格式化错误
            
            super().emit(record)
        except Exception:
            # 发生错误时静默处理，避免影响程序运行
            self.handleError(record)

# 日志级别相关函数
def log_debug(message):
    """记录调试级别日志"""
    if not logger:
        init_logger()
    logger.debug(message)  # 保持函数结构，但实际输出由日志系统控制

def log_info(message):
    """记录信息级别日志"""
    if not logger:
        init_logger()
    logger.info(message)

def log_warning(message):
    """记录警告级别日志"""
    if not logger:
        init_logger()
    logger.warning(message)

def log_error(message):
    """记录错误级别日志"""
    if not logger:
        init_logger()
    logger.error(message)

def log_critical(message):
    """记录严重错误级别日志"""
    if not logger:
        init_logger()
    logger.critical(message)

# 优化的异常日志记录
def log_exception(exception, additional_info=""):
    """
    记录异常信息（优化版本，避免日志过长）
    
    Args:
        exception: 异常对象
        additional_info: 额外的上下文信息
    """
    if not logger:
        init_logger()
    
    # 获取异常的基本信息
    exc_type = type(exception).__name__
    exc_message = str(exception)
    
    # 限制异常消息长度
    if len(exc_message) > 500:
        exc_message = exc_message[:500] + "... [消息过长已截断]"
    
    # 优化堆栈信息记录，避免过长
    traceback_lines = traceback.format_exc().split('\n')
    # 只记录最近的10层调用堆栈，避免过长
    if len(traceback_lines) > 15:
        traceback_str = '\n'.join(traceback_lines[:5])  # 保留异常类型和前几行
        traceback_str += '\n... [中间堆栈已省略]\n'
        traceback_str += '\n'.join(traceback_lines[-10:])  # 保留最近的调用信息
    else:
        traceback_str = '\n'.join(traceback_lines)
    
    # 构建优化的错误信息
    error_info = f"异常: {exc_type}\n信息: {exc_message}\n"
    if additional_info:
        # 限制附加信息长度
        if len(additional_info) > 200:
            additional_info = additional_info[:200] + "... [信息过长已截断]"
        error_info += f"上下文: {additional_info}\n"
    error_info += f"堆栈: {traceback_str}"
    
    logger.error(error_info)
    return error_info

# 异常处理装饰器
def log_exceptions(func):
    """函数异常处理装饰器，捕获并记录函数执行过程中的异常"""
    def wrapper(*args, **kwargs):
        try:
            # 执行原始函数
            return func(*args, **kwargs)
        except Exception as e:
            # 获取调用信息
            func_name = func.__name__
            module_name = func.__module__
            
            # 记录异常信息
            log_error(f"函数 '{module_name}.{func_name}' 执行异常")
            log_exception(e, f"调用参数: args={args}, kwargs={kwargs}")
            
            # 重新抛出异常以便调用者处理
            raise
    
    # 保留原函数的元数据
    wrapper.__name__ = func.__name__
    wrapper.__doc__ = func.__doc__
    wrapper.__module__ = func.__module__
    
    return wrapper

# 性能监控装饰器
def log_performance(func):
    """函数性能监控装饰器，记录函数执行时间"""
    def wrapper(*args, **kwargs):
        start_time = datetime.now()
        try:
            result = func(*args, **kwargs)
            return result
        finally:
            end_time = datetime.now()
            execution_time = (end_time - start_time).total_seconds()
            
            # 只记录执行时间超过1秒的函数
            if execution_time > 1.0:
                log_info(f"函数 '{func.__name__}' 执行时间: {execution_time:.2f} 秒")
    
    # 保留原函数的元数据
    wrapper.__name__ = func.__name__
    wrapper.__doc__ = func.__doc__
    wrapper.__module__ = func.__module__
    
    return wrapper

# 确保在模块导入时初始化日志系统
init_logger()